package top.changwen.speedview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Description: 速度
 * Author: LEI
 * Date: 2018/4/11 16:37
 */
public class SpeedView extends View {

    private final static int DEFAULT_CIRCLE_WIDTH = 150;
    private final static int DEFAULT_CIRCLE_HEIGHT = 150;
    private final static float DEFAULT_START_ANGLE = 0;// 默认从3点钟方向开始

    private final static String DEFAULT_OUTER_CIRCLE_COLOR = "#A2DCE6";
    private final static String DEFAULT_OUTER_ARC_COLOR = "#51D4F1";
    private final static String DEFAULT_INNER_ARC_COLOR = "#BBF1FD";
    private final static String DEFAULT_SPEED_TEXT_COLOR = "#0085A2";
    private final static String DEFAULT_SCALE_CIRCLE_COLOR = "#0085A2";

    private final static String WARNING_OUTER_CIRCLE_COLOR = "#FD8E8A";
    private final static String WARNING_OUTER_ARC_COLOR = "#F44444";
    private final static String WARNING_INNER_ARC_COLOR = "#FFB3B3";
    private final static String WARNING_SPEED_TEXT_COLOR = "#F44444";
    private final static String WARNING_SCALE_CIRCLE_COLOR = "#9E0000";

    private static final float maxAngle = 360;//可以画弧的最大角度
    private static final double maxSpeed = 150;
    private static final double minSpeed = 0;
    private final int DEFAULT_PADDING = dipToPx(15f);// 加padding保证外环阴影显示完整

    private Paint mOuterCriclePaint;// 外环
    private Paint mOuterShadePaint;// 外环阴影
    private Paint mOuterArcPaint;// 速度（外环）
    private Paint mInnerArcPaint;//速度（内环）
    private Paint mCurrentSpeedPaint;// 当前速度
    private Paint mScaleCriclePaint;// 刻度表圆环
    private Paint mScalePaint;// 刻度
    private Paint mScalePaint__;// 刻度__(白色)

    private float mWidth; // 控件宽度
    private float mHeight;// 控件高度
    private float centerX;// 圆心X坐标
    private float centerY;// 圆心Y坐标

    private String mOuterCircleColor = DEFAULT_OUTER_CIRCLE_COLOR;
    private String mOuterArcColor = DEFAULT_OUTER_ARC_COLOR;
    private String mInnerArcColor = DEFAULT_INNER_ARC_COLOR;
    private String mScaleCircleColor = DEFAULT_SCALE_CIRCLE_COLOR;

    private float mOuterCircleRadius;//外环半径
    private float mOuterCircleStrokeWidth = dipToPx(0.5f);// 外环宽度
    private float mOuterShadeStrokeWidth;// 外环阴影宽度
    private float mOuterArcStrokeWidth = dipToPx(3.8f);
    private float mInnerArcStrokeWidth = dipToPx(5.8f);
    private float mScaleStrokeWidth = dipToPx(0.8f);
    private float mScaleCricleRadius;
    private int mOuterShadeAlpha = 90;// 外环阴影透明度
    private float mStartAngle = DEFAULT_START_ANGLE;
    private float mSweepAngle;
    private double mSpeed;
    private double mLimitSpeed;
    private float mSpeedTextSize = dipToPx(16);
    private String mSpeedTextColor = DEFAULT_SPEED_TEXT_COLOR;

    public SpeedView(Context context) {
        this(context, null);
    }

    public SpeedView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SpeedView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SpeedView);

        try {
            mWidth = typedArray.getDimension(R.styleable.SpeedView_sv_width, DEFAULT_CIRCLE_WIDTH);
            mHeight = typedArray.getDimension(R.styleable.SpeedView_sv_height, DEFAULT_CIRCLE_HEIGHT);
            mOuterCircleStrokeWidth = typedArray.getDimension(R.styleable.SpeedView_sv_outer_stroke_width, dipToPx(1));
            mSpeed = typedArray.getInt(R.styleable.SpeedView_sv_speed, 0);
            mSpeedTextSize = typedArray.getDimensionPixelSize(R.styleable.SpeedView_sv_speed_text_size, dipToPx(20));
            mStartAngle = typedArray.getFloat(R.styleable.SpeedView_sv_arc_start_angle, DEFAULT_START_ANGLE);
        } finally {
            typedArray.recycle();
        }

        calculateCircle();
        setSpeed(mSpeed);

        // 外环
        mOuterCriclePaint = new Paint();
        mOuterCriclePaint.setAntiAlias(true);
        mOuterCriclePaint.setStyle(Paint.Style.STROKE);
        mOuterCriclePaint.setStrokeWidth(mOuterCircleStrokeWidth);

        // 外环阴影
        mOuterShadePaint = new Paint();
        mOuterShadePaint.setAntiAlias(true);
        mOuterShadePaint.setStyle(Paint.Style.STROKE);
        mOuterShadePaint.setStrokeWidth(mOuterShadeStrokeWidth);

        // 速度（外环）
        mOuterArcPaint = new Paint();
        mOuterArcPaint.setAntiAlias(true);
        mOuterArcPaint.setStyle(Paint.Style.STROKE);
        mOuterArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mOuterArcPaint.setStrokeWidth(mOuterArcStrokeWidth);

        // 速度（内环）
        mInnerArcPaint = new Paint();
        mInnerArcPaint.setAntiAlias(true);
        mInnerArcPaint.setStyle(Paint.Style.STROKE);
        mInnerArcPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mInnerArcPaint.setStrokeWidth(mInnerArcStrokeWidth);

        // 当前速度值
        mCurrentSpeedPaint = new Paint();
        mCurrentSpeedPaint.setAntiAlias(true);
        mCurrentSpeedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mCurrentSpeedPaint.setTextSize(mSpeedTextSize);

        // 刻度表圆环
        mScaleCriclePaint = new Paint();
        mScaleCriclePaint.setAntiAlias(true);
        mScaleCriclePaint.setStyle(Paint.Style.STROKE);
        mScaleCriclePaint.setStrokeWidth(mScaleStrokeWidth);

        // 刻度
        mScalePaint = new Paint();
        mScalePaint.setAntiAlias(true);
        mScalePaint.setStyle(Paint.Style.STROKE);
        mScalePaint.setStrokeWidth(mScaleStrokeWidth * 1.2f);

        // 刻度__(白色)
        mScalePaint__ = new Paint();
        mScalePaint__.setAntiAlias(true);
        mScalePaint__.setStyle(Paint.Style.STROKE);
        mScalePaint__.setStrokeWidth(mScaleStrokeWidth * 1.2f);
        mScalePaint__.setColor(Color.parseColor("#FFFFFF"));
    }

    private int dipToPx(float dip) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

    private void calculateCircle() {
        centerX = mWidth / 2 + DEFAULT_PADDING;
        centerY = mHeight / 2 + DEFAULT_PADDING;
        mOuterCircleRadius = Math.min(mWidth, mHeight) / 2;
        mOuterShadeStrokeWidth = mOuterCircleStrokeWidth + dipToPx(3.2f);
        mScaleCricleRadius = mOuterCircleRadius - dipToPx(3.2f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawOuterCricle(canvas);
        drawArc(canvas);
        drawSpeedText(canvas);
        drawScale(canvas);
    }

    private void drawOuterCricle(Canvas canvas) {
        mOuterShadePaint.setColor(Color.parseColor(mOuterCircleColor));
        mOuterShadePaint.setAlpha(mOuterShadeAlpha);
        mOuterCriclePaint.setColor(Color.parseColor(mOuterCircleColor));
        canvas.drawCircle(centerX, centerY, mOuterCircleRadius, mOuterShadePaint);
        canvas.drawCircle(centerX, centerY, mOuterCircleRadius, mOuterCriclePaint);
    }

    private void drawArc(Canvas canvas) {
        final float temp = dipToPx(3.2f);
        RectF mOuterArcRectF = new RectF();
        float outerX = centerX - mWidth * 1 / 3 - temp;
        float outerY = centerY - mHeight * 1 / 3 - temp;
        mOuterArcRectF.top = outerX;
        mOuterArcRectF.left = outerY;
        mOuterArcRectF.right = outerX + mWidth * 2 / 3 + temp * 2;
        mOuterArcRectF.bottom = outerY + mHeight * 2 / 3 + temp * 2;

        RectF mInnerArcRectF = new RectF();
        float innerX = centerX - mWidth * 1 / 3 + mOuterArcStrokeWidth - temp;
        float innerY = centerY - mHeight * 1 / 3 + mOuterArcStrokeWidth - temp;
        mInnerArcRectF.top = innerX;
        mInnerArcRectF.left = innerY;
        mInnerArcRectF.right = innerX + mWidth * 2 / 3 - mOuterArcStrokeWidth * 2 + temp * 2;
        mInnerArcRectF.bottom = innerY + mHeight * 2 / 3 - mOuterArcStrokeWidth * 2 + temp * 2;

        mOuterArcPaint.setColor(Color.parseColor(mOuterArcColor));
        mInnerArcPaint.setColor(Color.parseColor(mInnerArcColor));
        canvas.drawArc(mInnerArcRectF, mStartAngle, mSweepAngle, false, mInnerArcPaint);
        canvas.drawArc(mOuterArcRectF, mStartAngle, mSweepAngle, false, mOuterArcPaint);
    }

    private void drawSpeedText(Canvas canvas) {
        RectF rect = new RectF();
        float x = centerX - mWidth * 1 / 3;
        float y = centerY - mHeight * 1 / 3;
        rect.top = x;
        rect.left = y;
        rect.right = x + mWidth * 2 / 3;
        rect.bottom = y + mHeight * 2 / 3;

        mCurrentSpeedPaint.setColor(Color.parseColor(mSpeedTextColor));
        //该方法即为设置基线上那个点为center
        mCurrentSpeedPaint.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = mCurrentSpeedPaint.getFontMetrics();
        float top = fontMetrics.top;//为基线到字体上边框的距离
        float bottom = fontMetrics.bottom;//为基线到字体下边框的距离
        int baseLineY = (int) (rect.centerY() - top / 2 - bottom / 2);//基线中间点的y轴计算公式
        //速度
        canvas.drawText(Integer.toString((int) mSpeed),
                rect.centerX(),
                baseLineY,
                mCurrentSpeedPaint);
    }

    private void drawScale(Canvas canvas) {
        // 1.画圆环
        mScaleCriclePaint.setColor(Color.parseColor(mScaleCircleColor));
        canvas.drawCircle(centerX, centerY, mScaleCricleRadius, mScaleCriclePaint);

        final float temp = dipToPx(1.8f);
        float startX = centerX + mScaleCricleRadius;
        float startY = centerY;
        float stopY = centerY;
        // 2.画刻度
        mScalePaint.setColor(Color.parseColor(mScaleCircleColor));
        for (int i = 0; i < 6; i++) {
            // 先画白色的刻度
            canvas.drawLine(
                    startX,
                    startY,
                    startX - mInnerArcStrokeWidth - mOuterArcStrokeWidth - temp,
                    stopY,
                    mScalePaint__);
            canvas.drawLine(
                    startX,
                    startY,
                    startX - mOuterArcStrokeWidth - temp,
                    stopY,
                    mScalePaint);
            //设置旋转角度，以圆心为原点旋转
            canvas.rotate(60, centerX, centerY);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = (int) (mWidth + 2 * DEFAULT_PADDING);
        int height = (int) (mHeight + 2 * DEFAULT_PADDING);
        setMeasuredDimension(width, height);
    }

    public double getSpeed() {
        return mSpeed;
    }

    public void setSpeed(double speed) {
        if (speed < minSpeed) speed = minSpeed;
        if (speed > maxSpeed) speed = maxSpeed;
        mSpeed = speed;

        mSweepAngle = (float) (speed / maxSpeed) * maxAngle;

        if (mSpeed > mLimitSpeed) {
            mOuterCircleColor = WARNING_OUTER_CIRCLE_COLOR;
            mOuterArcColor = WARNING_OUTER_ARC_COLOR;
            mInnerArcColor = WARNING_INNER_ARC_COLOR;
            mSpeedTextColor = WARNING_SPEED_TEXT_COLOR;
            mScaleCircleColor = WARNING_SCALE_CIRCLE_COLOR;
        } else {
            mOuterCircleColor = DEFAULT_OUTER_CIRCLE_COLOR;
            mOuterArcColor = DEFAULT_OUTER_ARC_COLOR;
            mInnerArcColor = DEFAULT_INNER_ARC_COLOR;
            mSpeedTextColor = DEFAULT_SPEED_TEXT_COLOR;
            mScaleCircleColor = DEFAULT_SCALE_CIRCLE_COLOR;
        }

        invalidate();
    }

    public void setLimitSpeed(double limitSpeed) {
        if (limitSpeed < minSpeed) limitSpeed = minSpeed;
        if (limitSpeed > maxSpeed) limitSpeed = maxSpeed;
        mLimitSpeed = limitSpeed;
        invalidate();
    }

    public void setSpeed(double speed, double limitSpeed) {
        setLimitSpeed(limitSpeed);
        setSpeed(speed);
    }
}
